﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace TeF.Runner.UI
{
    public class HierarchicalItemViewModel : INotifyPropertyChanged 
    {
        #region Constructors

        private HierarchicalItemViewModel()
        {
            IsExpanded = true;
            IsSelected = false;
        }

        private HierarchicalItemViewModel(ITestEntity testEntity)
            : this()
        {
            if (testEntity == null)
                throw new ArgumentNullException("testEntity");

            TestEntity = testEntity;
            Name = testEntity.Name;
            
            State = testEntity.State;
            testEntity.StateChanged += TestEntity_StateChanged;
            testEntity.LogChanged += TestEntity_LogChanged;
        }

        public HierarchicalItemViewModel(ITestAssembly testAssembly)
            : this((ITestEntity)testAssembly)
        {
            Items = testAssembly.Namespaces.Select(i => new HierarchicalItemViewModel(i)).ToArray();
        }

        public HierarchicalItemViewModel(ITestNamespace testNamespace)
            : this((ITestEntity)testNamespace)
        {
            Items = testNamespace.Containers.Select(i => new HierarchicalItemViewModel(i)).ToArray();
        }

        public HierarchicalItemViewModel(ITestContainer testContainer)
            : this((ITestEntity)testContainer)
        {
            Items = testContainer.Tests.Select(i => new HierarchicalItemViewModel(i)).ToArray();
        }

        public HierarchicalItemViewModel(ITest test)
            : this((ITestEntity)test)
        {
            Items = new HierarchicalItemViewModel[] { };
        }

        #endregion


        #region Properties

        public ITestEntity TestEntity { get; private set; }

        public string Name { get; private set; }
        public IEnumerable<HierarchicalItemViewModel> Items { get; private set; }

        public TestState State
        {
            get
            {
                return _state;
            }
            set
            {
                _state = value;
                FirePropertyChanged("State");
            }
        }
        private TestState _state;

        public string Log
        {
            get
            {
                return _log;
            }
            set
            {
                _log = value;
                FirePropertyChanged("Log");
            }
        }
        private string _log; 

        public bool IsExpanded
        {
            get
            {
                return _isExpanded;
            }
            set
            {
                _isExpanded = value;
                FirePropertyChanged("IsExpanded");
            }
        }
        private bool _isExpanded;
        
        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                _isSelected = value;
                FirePropertyChanged("IsSelected");
            }
        }
        private bool _isSelected; 
        
        #endregion


        #region Event Handlers

        private void TestEntity_StateChanged(object sender, StateChangedEventArgs args)
        {
            State = args.State;
        }

        private void TestEntity_LogChanged(object sender, LogChangedEventArgs args)
        {
            Log = args.Log;
        }

        #endregion


        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        private void FirePropertyChanged(string propertyName)
        {
            if (propertyName == null)
                throw new ArgumentNullException("propertyName");

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }
}
